// Copyright 2012 Google Inc. All Rights Reserved.

package com.google.superlists.servlet;

import com.google.api.client.googleapis.batch.BatchRequest;
import com.google.api.services.tasks.Tasks;
import com.google.api.services.tasks.Tasks.Tasklists.Get;
import com.google.api.services.tasks.Tasks.TasksOperations;
import com.google.api.services.tasks.model.Task;
import com.google.api.services.tasks.model.TaskList;
import com.google.common.util.concurrent.Futures;
import com.google.superlists.model.ActionResult;
import com.google.superlists.model.SuperList;
import com.google.superlists.model.SuperListItem;
import com.google.superlists.model.TaskListData;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.Future;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Action handling an import of a task list.
 *
 * @author sven@google.com (Sven Mawson)
 */
public class ImportAction extends SaveAction {

  private final String data;

  public ImportAction(
      HttpServlet servlet, HttpServletRequest req, HttpServletResponse resp, String data) {
    super(servlet, req, resp, null);
    this.data = data;
  }

  @Override
  protected ActionResult handle() throws IOException {
    TaskListData action = TaskListData.fromJson(data);
    String tasklistId = action.id;
    SuperList list = new SuperList();
    list.id = "";

    Tasks tasks = getTasksService();

    importTasklist(tasks, list, tasklistId);
    list.content.tasklistId = tasklistId;

    // Save the list we imported from the tasks service.
    String savedId = saveList(list);

    ActionResult result = new ActionResult();
    result.id = savedId;
    return result;
  }

  /**
   * Imports a tasklist into the given SuperList.
   */
  private void importTasklist(Tasks tasksService, final SuperList list, String tasklistId)
      throws IOException {

    Get getRequest = tasksService.tasklists().get(tasklistId);
    if (usePartialResponses()) {
      getRequest.setFields("title");
    }
    
    TasksOperations.List listRequest = tasksService.tasks().list(tasklistId);
    if (usePartialResponses()) {
      listRequest.setFields("items(id,title,notes,status)");
    }

    Future<TaskList> tasklistFuture;
    Future<com.google.api.services.tasks.model.Tasks> tasksFuture;
    if (useBatch()) {
      BatchRequest batch = tasksService.batch();
      
      FutureCallback<TaskList> getCallback = createCallback("import.tasklists.getLength");
      getRequest.queue(batch, getCallback);
      tasklistFuture = getCallback.getFuture();

      FutureCallback<com.google.api.services.tasks.model.Tasks> listCallback =
          createCallback("import.tasks.listLength");
      listRequest.queue(batch, listCallback);
      tasksFuture = listCallback.getFuture();

      String name = "import.batch(" + batch.size() + ")";
      start(name);
      batch.execute();
      stop(name);
    } else {
      start("import.tasklists.get()");
      TaskList tasklist = getRequest.execute();
      tasklistFuture = Futures.immediateFuture(tasklist);
      addContentLength("import.tasklists.getLength", tasklist.getResponseHeaders());
      addContentLength("response.size", tasklist.getResponseHeaders());
      stop("import.tasklists.get()");

      start("import.tasks.list()");
      com.google.api.services.tasks.model.Tasks tasks = listRequest.execute();
      tasksFuture = Futures.immediateFuture(tasks);
      addContentLength("import.tasks.listLength", tasks.getResponseHeaders());
      addContentLength("response.size", tasks.getResponseHeaders());
      stop("import.tasks.list()");
    }

    // Set the title and import all of the items.
    list.name = Futures.getUnchecked(tasklistFuture).getTitle();
    importItems(list, Futures.getUnchecked(tasksFuture).getItems());
  }

  /** Imports the task items into the list. */
  private void importItems(SuperList list, List<Task> items) {
    if (items != null) {
      for (Task task : items) {
        SuperListItem item = new SuperListItem();
        item.taskId = task.getId();
        item.name = task.getTitle();
        item.description = task.getNotes();
        item.status = task.getStatus();
        list.content.items.add(item);
      }
    }
  }
}
